package tr3dtris.game.models.pieces;

import java.util.logging.Level;
import java.util.logging.Logger;
import tr3dtris.game.models.CellArray;

/**
 * Static class to simply instantiate a new <AbstractPiece> of basic type.
 * @author Luciano Mammino <loige@hotmail.com>
 * @author Andrea Mangano <kapitan0@hotmail.it>
 * @version 0.1
 * @since 0.1
 */
public class PieceFactory
{
    /**
     * Total number of basic pieces
     */
    private static final int NUM_PIECES_TYPES = 7;

    /**
     * The reference parentGrid
     */
    private CellArray parentGrid;


    public PieceFactory(CellArray parentGrid)
    {
        this.parentGrid = parentGrid;
    }


    /**
     * Creates a new random <BasicPiece> at the position [0,0]
     * @return the created piece
     */
    public AbstractPiece createRandomBasicPiece()
    {
        AbstractPiece piece = null;
        try
        {
          int pieceType = (int)(Math.random() * NUM_PIECES_TYPES + 1);
            piece = this.createBasicPieceByTypeId(pieceType);
        } catch (PieceTypeNotFoundException ex)
        {
            Logger.getLogger(PieceFactory.class.getName()).log(Level.SEVERE, null, ex);
        }
        return piece;
    }

    /**
     * Creates a new random <BasicPiece> at the position [x,y]
     * @param x X coordinate for the piece creation
     * @param y Y coordinate for the piece creation
     * @return the created piece
     */
    public AbstractPiece createRandomBasicPiece(int x, int y)
    {
        AbstractPiece piece = null;
        try
        {
          int pieceType = (int)(Math.random() * NUM_PIECES_TYPES + 1);
            piece = this.createBasicPieceByTypeId(x, y, pieceType);
        } catch (PieceTypeNotFoundException ex)
        {
            Logger.getLogger(PieceFactory.class.getName()).log(Level.SEVERE, null, ex);
        }
        return piece;
    }

    /**
     * Creates a new random <BasicPiece> at the position [x,y]
     * @param x X coordinate for the piece creation
     * @param y Y coordinate for the piece creation
     * @param blockType the type for blocks
     * @return
     */
    public AbstractPiece createRandomBasicPiece(int x, int y, int blockType)
    {
        AbstractPiece piece = null;
        try
        {
          int pieceType = (int)(Math.random() * NUM_PIECES_TYPES + 1);
            piece = this.createBasicPieceByTypeId(x, y, pieceType , blockType);
        } catch (PieceTypeNotFoundException ex)
        {
            Logger.getLogger(PieceFactory.class.getName()).log(Level.SEVERE, null, ex);
        }
        return piece;
    }

    /**
     * Creates a new Block using a given typeId
     * @param typeId one of the following types:
     * 1 -  I
     * 2 -  L
     * 3 -  L mirror
     * 4 -  S
     * 5 -  S mirror
     * 6 -  T
     * 7 -  Square
     * @return
     * @throws PieceTypeNotFoundException if the type id is not found
     */
    public AbstractPiece createBasicPieceByTypeId(int typeId) throws PieceTypeNotFoundException
    {
        return this.createBasicPieceByTypeId(0, 0, typeId, typeId);
    }

    public AbstractPiece createBasicPieceByTypeId(int x, int y, int typeId) throws PieceTypeNotFoundException
    {
        return this.createBasicPieceByTypeId(x, y, typeId, typeId);
    }

    /**
     * Creates a new piece using a given typeId, given coordinates, and given
     * blockType for each block in the piece.
     * @param x X coordinate
     * @param y Y coordinate
     * @param typeId {@inheritDoc}
     * @param blockType
     * @return
     * @throws PieceTypeNotFoundException {@inheritDoc}
     */
    public AbstractPiece createBasicPieceByTypeId(int x, int y, int typeId, int blockType) throws PieceTypeNotFoundException
    {
        AbstractPiece piece = null;

        switch(typeId)
        {
            case 1:
                piece = new PieceI(x, y, this.parentGrid, blockType);
                break;
                
            case 2:
                piece = new PieceL(x, y, this.parentGrid, blockType);
                break;

            case 3:
                piece = new PieceLMirror(x, y, this.parentGrid, blockType);
                break;

            case 4:
                piece = new PieceS(x, y, this.parentGrid, blockType);
                break;

            case 5:
                piece = new PieceSMirror(x, y, this.parentGrid, blockType);
                break;

            case 6:
                piece = new PieceT(x, y, this.parentGrid, blockType);
                break;

            case 7:
                piece = new PieceSquare(x, y, this.parentGrid, blockType);
                break;

            default:
                throw new PieceTypeNotFoundException(typeId);
        }

        return piece;

    }

}
